package cl.utfsm.inf.lp.sem12013.tarea2.logic;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cl.utfsm.inf.lp.sem12013.tarea2.gui.GameUITile;

/**
 * @author Shago
 *
 */
public class EntityManager {
	
	public static final int ENTITY_TYPE_HOUSE = 1;
	public static final int ENTITY_TYPE_OILWELL = 2;
	public static final int ENTITY_TYPE_REFINERY = 3;
	public static final int ENTITY_TYPE_WATERENTITY = 4;

	private GameManager gm;
	private Map <Point, HouseEntity> houses = new HashMap<Point, HouseEntity>();
	private Map <Point, OilwellEntity> oilwells = new HashMap<Point, OilwellEntity>();
	private Map <Point, RefineryEntity> refineries = new HashMap<Point, RefineryEntity>();
	private Map <Point, WaterEntity> waterEntities = new HashMap<Point, WaterEntity>();
	private List<EntityAbstract> entities = new ArrayList<EntityAbstract>();
	
	/**
	 * @param gm Manager principal del juego.
	 */
	public EntityManager(GameManager gm) {
		this.gm = gm;
		this.loadMap();
	}
	
	/**
	 * 
	 */
	public void loadMap(){
		int height = this.gm.window.getDimension().height;
		int width = this.gm.window.getDimension().width;
		for(int i=0; i<height;i++){
			for(int j=0; j<width; j++){
				if(this.gm.isABuilding(j, i))
					this.newEntity(new Point(j,i));
			}
		}
	}
	
	public void updateEntities() {
		for(int i=0;i<this.entities.size();i++)
			this.entities.get(i).updateEntityRes();
	}


	/**
	 * @param type
	 * @param entity
	 */
	public void addEntity(int type, EntityAbstract entity){
		this.entities.add(entity);
		switch(type){
			case ENTITY_TYPE_HOUSE:
				this.houses.put(((HouseEntity)entity).getLocationPoint(), (HouseEntity)entity);
				break;
			case ENTITY_TYPE_OILWELL:
				this.oilwells.put(entity.getLocationArray()[0], (OilwellEntity)entity);
				this.oilwells.put(entity.getLocationArray()[1], (OilwellEntity)entity);
				break;
			case ENTITY_TYPE_REFINERY:
				this.refineries.put(entity.getLocationArray()[0], (RefineryEntity)entity);
				this.refineries.put(entity.getLocationArray()[1], (RefineryEntity)entity);
				this.refineries.put(entity.getLocationArray()[2], (RefineryEntity)entity);
				this.refineries.put(entity.getLocationArray()[3], (RefineryEntity)entity);
				break;
			case ENTITY_TYPE_WATERENTITY:
				this.waterEntities.put(((WaterEntity)entity).getLocationPoint(), (WaterEntity)entity);
				break;
		}
	}
	
	/**
	 * @param p
	 */
	private void newEntity(Point p) {
		if(this.gm.window.getBooleanValueFromDescriptor(p.x, p.y, GameUITile.UI_REFINERY_MASK)){
			Point[] p2 = this.getEntityTiles(p,ENTITY_TYPE_REFINERY);
			RefineryEntity ref = new RefineryEntity(p2);
			this.addEntity(ENTITY_TYPE_REFINERY, ref);
		}
		if(this.gm.window.getBooleanValueFromDescriptor(p.x, p.y, GameUITile.UI_OILWELL_MASK)){
			Point[] p2 = this.getEntityTiles(p,ENTITY_TYPE_OILWELL);
			OilwellEntity oi = new OilwellEntity(p2);
			this.addEntity(ENTITY_TYPE_OILWELL, oi);
		}
		if(this.gm.window.getBooleanValueFromDescriptor(p.x, p.y, GameUITile.UI_WATERPUMP_MASK)){
			WaterEntity wa = new WaterEntity(WaterEntity.TYPE_WATERPUMP, p, "Bomba de agua");
			this.addEntity(ENTITY_TYPE_WATERENTITY, wa);
			
		}
		if(this.gm.window.getBooleanValueFromDescriptor(p.x, p.y, GameUITile.UI_WATERTOWER_MASK)){
			WaterEntity wa = new WaterEntity(WaterEntity.TYPE_WATERTOWER, p, "Torre de agua");
			this.addEntity(ENTITY_TYPE_WATERENTITY, wa);
		}
		if(this.gm.window.getBooleanValueFromDescriptor(p.x, p.y, GameUITile.UI_HOUSE_MASK)){
			if(this.gm.window.getLongIntegerValueFromDescriptor(p.x, p.y, GameUITile.UI_HOUSE_TYPE_MASK)==GameUITile.UI_HOUSE_TYPE_1){
				HouseEntity house = new HouseEntity(HouseEntity.HOUSE_TYPE_1, p, "Casa Tipo1");
				this.addEntity(ENTITY_TYPE_HOUSE, house);
			}
			if(this.gm.window.getLongIntegerValueFromDescriptor(p.x, p.y, GameUITile.UI_HOUSE_TYPE_MASK)==GameUITile.UI_HOUSE_TYPE_2){
				HouseEntity house = new HouseEntity(HouseEntity.HOUSE_TYPE_2, p, "Casa Tipo2");
				this.addEntity(ENTITY_TYPE_HOUSE, house);
			}
			if(this.gm.window.getLongIntegerValueFromDescriptor(p.x, p.y, GameUITile.UI_HOUSE_TYPE_MASK)==GameUITile.UI_HOUSE_TYPE_3){
				HouseEntity house = new HouseEntity(HouseEntity.HOUSE_TYPE_3, p, "Casa Tipo3");
				this.addEntity(ENTITY_TYPE_HOUSE, house);
			}
			if(this.gm.window.getLongIntegerValueFromDescriptor(p.x, p.y, GameUITile.UI_HOUSE_TYPE_MASK)==GameUITile.UI_HOUSE_TYPE_4){
				HouseEntity house = new HouseEntity(HouseEntity.HOUSE_TYPE_4, p, "Casa Tipo4");
				this.addEntity(ENTITY_TYPE_HOUSE, house);
			}
		}
	}

	private Point[] getEntityTiles(Point p, int entityType){
		Point[] tiles;
		int count = 1;
		switch(entityType){
			case ENTITY_TYPE_OILWELL:
				tiles = new Point[2];
				tiles[0] = (Point)p.clone();
				if(this.gm.window.getBooleanValueFromDescriptor(p.x+1, p.y, GameUITile.UI_OILWELL_MASK)){
					tiles[1] = new Point(p.x+1,p.y);
					count++;
				}
				if(count < 2 && this.gm.window.getBooleanValueFromDescriptor(p.x-1, p.y, GameUITile.UI_OILWELL_MASK)){
					tiles[1] = new Point(p.x-1,p.y);
					count++;
				}
				if(count < 2 && this.gm.window.getBooleanValueFromDescriptor(p.x, p.y+1, GameUITile.UI_OILWELL_MASK)){
					tiles[1] = new Point(p.x,p.y+1);
					count++;
				}
				if(count < 2 && this.gm.window.getBooleanValueFromDescriptor(p.x, p.y-1, GameUITile.UI_OILWELL_MASK)){
					tiles[1] = new Point(p.x,p.y-1);
					count++;
				}
				return tiles;
			case ENTITY_TYPE_REFINERY:
				tiles = new Point[4];
				tiles[0] = (Point)p.clone();
				if(this.gm.window.getBooleanValueFromDescriptor(p.x+1, p.y, GameUITile.UI_REFINERY_MASK)){
					tiles[count] = new Point(p.x+1,p.y);
					count++;
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x+1, p.y+1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x+1,p.y+1);
						count++;
					}
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x+1, p.y-1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x+1,p.y-1);
						count++;
					}
				}
				if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x-1, p.y, GameUITile.UI_REFINERY_MASK)){
					tiles[count] = new Point(p.x-1,p.y);
					count++;
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x-1, p.y+1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x-1,p.y+1);
						count++;
					}
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x-1, p.y-1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x-1,p.y-1);
						count++;
					}
				}
				if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x, p.y+1, GameUITile.UI_REFINERY_MASK)){
					tiles[count] = new Point(p.x,p.y+1);
					count++;
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x+1, p.y+1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x+1,p.y+1);
						count++;
					}
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x-1, p.y+1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x-1,p.y+1);
						count++;
					}
				}
				if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x, p.y-1, GameUITile.UI_REFINERY_MASK)){
					tiles[count] = new Point(p.x,p.y-1);
					count++;
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x+1, p.y-1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x+1,p.y-1);
						count++;
					}
					if(count < 4 && this.gm.window.getBooleanValueFromDescriptor(p.x-1, p.y-1, GameUITile.UI_REFINERY_MASK)){
						tiles[count] = new Point(p.x-1,p.y-1);
						count++;
					}
				}
				return tiles;
		}
		return null;
	}


}
